#ifndef CLIB_CLIB_CONTAINER_HASH_SET_H
#define CLIB_CLIB_CONTAINER_HASH_SET_H

#include "../hash_map/clib_container_hash_map.h"

/**
 * hashset对象
 */
struct clib_container_hash_set;

/**
 * hashset配置对象
 */
struct clib_container_hash_set_conf {
    /**
     * 负载因子决定了bucket表数组的增长方式。
     * 例如，如果负载因子为 0.5，数组容量为 100，则在添加第 50 个条目后将触发调整大小。
     */
    float load_factor;

    /**
     * bucket表数组的初始容量。
     */
    size_t initial_capacity;

    /**
     * 密钥的长度
     */
    int key_length;

    /**
     * 哈希种子
     */
    clib_uint32_t hash_seed;

    /**
     * hash函数
     * @param key key
     * @param length 长度
     * @param seed 种子
     * @return
     */
    size_t (*hash_func)(const void *key, size_t length, clib_uint32_t seed);

    /**
     * 键的比较函数
     * @param key1 键1
     * @param key2 键2
     * @return
     */
    int (*key_compare_func)(const void *key1, const void *key2, size_t key_length);

    /**
     * 内存分配函数
     * @param size 需要分配的大小
     * @return
     */
    void *(*mem_malloc_func)(size_t size);

    /**
     * 内存释放函数
     * @param block 块指针
     */
    void (*mem_free_func)(void *block);

    /**
     * 内存拷贝函数
     * @param target 目标
     * @param src 源
     * @param size 大小
     * @return
     */
    void *(*mem_copy_func)(void *target,const void *src, size_t size);
};


/**
 * 创建hashset
 * @param conf 配置信息
 * @param hash_set 生成的hashset对象
 * @return
 * 成功 0
 * 失败 非0
 */
int clib_container_hash_set_create_with_conf(struct clib_container_hash_set_conf *conf,
                                             struct clib_container_hash_set **hash_set);

/**
 * 销毁hashset
 * @param set 要销毁的hashset
 */
void clib_container_hash_set_destroy(struct clib_container_hash_set *set);


/**
 * 向hashset中添加元素
 * 如果指定的添加元素hashset中不存在，则直接添加
 * 如果已存在并且指针相同则直接替换
 * 如果已存在并且指针不同，替换后，将原来的数据指针添加到pre_value数组中，用户可以自行释放或忽略
 * @param set hashset对象
 * @param element 要添加的元素
 * @param pre_value 存储替换之前的元素，如果值指针相同的元素不在返回信息里面，忽略则传入NULL
 * @return
 * 成功 0
 * 失败 非0
 */
int clib_container_hash_set_add(struct clib_container_hash_set *set, void *element, void **pre_value);

/**
 * 删除hashset中元素
 * 删除之后的元素，将返回值指针到pre_value数组中，忽略传入NULL
 * @param set hashset对象
 * @param element 要添加的元素
 * @param pre_value 存储删除之前的元素，忽略则传入NULL
 * @return
 * 成功 0
 * 失败 非0
 */
int clib_container_hash_set_remove(struct clib_container_hash_set *set, void *element, void **pre_value);

/**
 * 删除hashset所有元素
 * 删除之后的元素，将返回值指针到pre_value数组中，忽略传入NULL
 * @param set hashset对象
 * @param out_values 存储删除之前的元素，忽略则传入NULL
 * @return
 * 删除元素的个数
 */
int clib_container_hash_set_remove_all(struct clib_container_hash_set *set, void *out_values[]);

/**
 * 判断元素是否在hashset中
 * @param set hashset对象
 * @param element 查询的元素
 * @return
 * 存在 true
 * 不存在 false
 */
bool clib_container_hash_set_contains(struct clib_container_hash_set *set, void *element);


/**
 * 获取当前元素的个数
 * @param set hashset对象
 * @return
 * 当前hashset元素个数
 */
size_t clib_container_hash_set_get_current_size(struct clib_container_hash_set *set);


/**
 * 获取hashset所有的值
 * @param set hashset对象
 * @param out_values 获取的元素
 * @return
 * 获取的元素个数
 */
size_t clib_container_hash_set_get_values(struct clib_container_hash_set *set, void *out_values[]);

#endif //CLIB_CLIB_CONTAINER_HASH_SET_H
